#include <string.h>
#include <stdio.h>
#include <cstdlib>

#include "main.h"
#include "usart.h"
#include "nbiot.h"
#include "oled.h"
#include "message.h"
#include "at.h"

static char s_acData[512] = {0};
static char s_acAtBuf[612] = {0};

NB_STA nbiot_check_LWM2M(int iTimeout);

void nbiot_send_at_cmd(char *pcCmd, int iDelay)
{
	//uart3_refresh_buf();  //清空模块返回数据的buff
	
	uart3_send_str(pcCmd);
	printf("\n%s",pcCmd); //回显到Console
	HAL_Delay(iDelay);
}

NB_STA nbiot_recv_at_resp(int iTry, char *pcResp, int *piSz)
{
	/*
	Responses will be of the format:
	<CR><LF>+CMD1:<parameters><CR><LF>
	<CR><LF>OK<CR><LF>
	Or
	<CR><LF><parameters><CR><LF>
	<CR><LF>OK<CR><LF>
	or
	<CR><LF>ERROR<CR><LF>
	
	Unsolicited information responses will never occur between a solicited informational response and the final “OK” or “ERROR”.
	*/
	NB_STA atRet = NB_TIMEOUT;
	int iSz = *piSz;
	int ch = 0, iLen = 0;//0 ok, 1 error, 2 pending
	char okFlag = 0, errFlag = 0;
	char acOK[] = {'O','K',0x0D,0x0A}, acErr[] = {'E','R','R','O','R',0x0D,0x0A};
	*piSz = 0;
	do{
		ch = uart3_get_ch();
		if(ch){
			pcResp[iLen++] = ch;
			if(iSz == iLen) break;
			//printf("%02X:%d - %d\n", ch, okFlag, errFlag);
			
			if(acOK[okFlag] == ch){
				okFlag++;
			}else{
				okFlag = 0;
			}
			
			if(acErr[errFlag] == ch){
				errFlag++;
			}else{
				errFlag = 0;
			}
			console_put_ch(ch);
			
			
			if(4 == okFlag){atRet = NB_OK; break;}
			if(7 == errFlag){atRet = NB_ERROR; break;}
		}else{
			if(0 != iTry) {
				iTry--;
				if(0 != iTry){
					HAL_Delay(1000);
				}
			}
		}
	}while(iTry);
	pcResp[iLen] = 0;
	*piSz = iLen;
	return atRet;
}

NB_STA nbiot_wait_reboot(int iTry)
{
	/*
	REBOOTING
?@?
Boot: Unsigned
Security B.. 

Verified
Protocol A.. 

Verified
Apps A...... 

Verified


REBOOT_CAUSE_APPLICATION_AT
Neul 
OK
*/
	NB_STA atRet = NB_TIMEOUT;

	int ch = 0;//0 ok, 1 error, 2 pending
	char okFlag = 0, rebootFlag = 0;
	char *acREBOOT = "REBOOT_CAUSE_APPLICATION_AT";
	char acOK[4] = {'O','K',0x0D,0x0A};
	do{
		ch = uart3_get_ch();
		if(ch){
			//printf("%02X:%d - %d\n", ch, okFlag, errFlag);
			console_put_ch(ch);
			if(27 != rebootFlag){
				if(acREBOOT[rebootFlag] == ch){
					rebootFlag++;
				}else{
					rebootFlag = 0;
				}
			}else{
				if(acOK[okFlag] == ch){
					okFlag++;
				}else{
					okFlag = 0;
				}
			}
			
			if(4 == okFlag){atRet = NB_OK; break;}
		}else{
			if(0 != iTry) {
				iTry--;
				if(0 != iTry){
					HAL_Delay(1000);
				}
			}
		}
	}while(iTry);
	return atRet;
}

NB_STA nbiot_module_init(void)
{
	NB_STA atRet;
	int iLen = 0;
	int iTry = 0;
	char acShow[16] = {0};
	OLED_ShowString(0, 0, (uint8_t *)"Check Module...", 8);
	nbiot_send_at_cmd(AT, 300);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(10, s_acAtBuf, &iLen);
	if(NB_OK != atRet) return atRet;

	printf("nb-iot module init\n");
	OLED_ShowString(0, 0, (uint8_t *)"Init module...", 8);
	
	nbiot_send_at_cmd(AT_W_NCONFIG_MANUL, 1000);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(NB_OK != atRet) return atRet;
	
	nbiot_send_at_cmd(AT_W_CFUN_0, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(10, s_acAtBuf, &iLen);
	
	nbiot_send_at_cmd(AT_W_NBAND, 500);// 频段设置
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(NB_OK != atRet) return atRet;
	
	nbiot_send_at_cmd(AT_NRB, 100);
	iLen = sizeof(s_acAtBuf);
	iTry = 15;
	do{
		sprintf(acShow,"%02ds",iTry);
		OLED_ShowString(0, 2, (uint8_t *)acShow, 8);
		atRet = nbiot_wait_reboot(1);
		HAL_Delay(1000);
		iTry--;
	}while(NB_TIMEOUT == atRet && 0 != iTry);
	OLED_ShowString(0, 2, (uint8_t *)"     ", 8);
	if(NB_OK != atRet) return atRet;
	
	HAL_Delay(1000);
	uart3_refresh_buf();
	OLED_ShowString(0, 0, (uint8_t *)"Up module...   ", 8);		
	
	
	nbiot_send_at_cmd(AT_W_CFUN_1, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(10, s_acAtBuf, &iLen);
	if(NB_OK != atRet) {
	OLED_ShowString(0, 0, (uint8_t *)"No SIM...      ", 8);
		while(1){HAL_Delay(100);};
	}
	
	nbiot_send_at_cmd(AT_STOP_eDRX, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(NB_OK != atRet) return atRet;

	nbiot_send_at_cmd(AT_STOP_PSM, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(NB_OK != atRet) return atRet;

	nbiot_send_at_cmd(AT_W_CGATT, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(NB_OK != atRet) return atRet;
	
	nbiot_send_at_cmd(AT_W_CEREG2, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	
	printf("Check SIM...\n");
	OLED_ShowString(0, 0, (uint8_t *)"Check SIM...    ", 8);
	do{
		nbiot_send_at_cmd(AT_CIMI, 1000);
		iLen = sizeof(s_acAtBuf);
		atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
		iTry++;
		if(2 == iTry){
	OLED_ShowString(0, 0, (uint8_t *)"No SIM...      ", 8);
		}
	}while(NB_OK != atRet); // no SIM 
	
	printf("Check network...\n");
	OLED_ShowString(0, 0, (uint8_t *)"Net registry...", 8);
	
	iTry = 120;
	do{
		HAL_Delay(500);
		sprintf(acShow,"%02ds ",iTry);
		OLED_ShowString(0, 2, (uint8_t *)acShow, 8);
		atRet = nbiot_check_reg(1);
		iTry--;
	}while(NB_TIMEOUT == atRet && 0 != iTry);
	
	OLED_ShowString(0, 2, (uint8_t *)"     ", 8);
	if(NB_OK != atRet){
	OLED_ShowString(0, 0, (uint8_t *)"Registry failed", 8);
	OLED_ShowString(0, 2, (uint8_t *)"Check Antenna", 8);
	
		while(1){
			//HAL_Delay(1000);
				do{
				UART_Forward();
			}while(0 == uart1_is_empty());
		}
	}else{
	OLED_ShowString(0, 0, (uint8_t *)"Registry success", 8);
	}
	return atRet;
}

NB_STA nbiot_OceanConnect_init(void)
{
	NB_STA atRet;
	int iLen = 0;
	int iTry = 0;
	char acShow[16] = {0};
	OLED_ShowString(0, 0, (uint8_t *)"Check Module...", 8);
	nbiot_send_at_cmd(AT, 300);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(10, s_acAtBuf, &iLen);
	if(NB_OK != atRet) return atRet;

	printf("nb-iot module init\n");
	OLED_ShowString(0, 0, (uint8_t *)"Init module...", 8);
	
	nbiot_send_at_cmd(AT_W_NCONFIG_MANUL, 1000);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(NB_OK != atRet) return atRet;
	
	nbiot_send_at_cmd(AT_W_CFUN_0, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(10, s_acAtBuf, &iLen);
	
	nbiot_send_at_cmd(AT_W_NBAND, 500);// 频段设置
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(NB_OK != atRet) return atRet;
	
	nbiot_send_at_cmd(AT_NRB, 100);
	iLen = sizeof(s_acAtBuf);
	iTry = 15;
	do{
		sprintf(acShow,"%02ds",iTry);
		OLED_ShowString(0, 2, (uint8_t *)acShow, 8);
		atRet = nbiot_wait_reboot(1);
		HAL_Delay(1000);
		iTry--;
	}while(NB_TIMEOUT == atRet && 0 != iTry);
	OLED_ShowString(0, 2, (uint8_t *)"     ", 8);
	if(NB_OK != atRet) return atRet;
	
	HAL_Delay(1000);
	uart3_refresh_buf();
	OLED_ShowString(0, 0, (uint8_t *)"Up module...   ", 8);
	
	nbiot_send_at_cmd(AT_W_NCDP_CHINA_TELE, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(NB_OK != atRet) return atRet;
	
	nbiot_send_at_cmd(AT_W_CFUN_1, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(10, s_acAtBuf, &iLen);
	if(NB_OK != atRet) {
	OLED_ShowString(0, 0, (uint8_t *)"No SIM...      ", 8);
		while(1){HAL_Delay(100);};
	}
	
	nbiot_send_at_cmd(AT_STOP_eDRX, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(NB_OK != atRet) return atRet;

	nbiot_send_at_cmd(AT_STOP_PSM, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(NB_OK != atRet) return atRet;
	
	nbiot_send_at_cmd(AT_W_CGDCONT_CTNB, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(NB_OK != atRet) return atRet;
	
	nbiot_send_at_cmd(AT_W_CGATT, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(NB_OK != atRet) return atRet;

	nbiot_send_at_cmd(AT_W_CEREG2, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	
	printf("Check SIM...\n");
	OLED_ShowString(0, 0, (uint8_t *)"Check SIM...    ", 8);
	do{
		nbiot_send_at_cmd(AT_CIMI, 1000);
		iLen = sizeof(s_acAtBuf);
		atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
		iTry++;
		if(2 == iTry){
	OLED_ShowString(0, 0, (uint8_t *)"No SIM...      ", 8);
		}
	}while(NB_OK != atRet); // no SIM 
	
	printf("Check network...\n");
	OLED_ShowString(0, 0, (uint8_t *)"Net registry...", 8);
	
	iTry = 120;
	do{
		HAL_Delay(500);
		sprintf(acShow,"%02ds ",iTry);
		OLED_ShowString(0, 2, (uint8_t *)acShow, 8);
		atRet = nbiot_check_reg(1);
		iTry--;
	}while(NB_TIMEOUT == atRet && 0 != iTry);
	
	OLED_ShowString(0, 2, (uint8_t *)"     ", 8);
	if(NB_OK != atRet){
	OLED_ShowString(0, 0, (uint8_t *)"Registry failed", 8);
	OLED_ShowString(0, 2, (uint8_t *)"Check Antenna", 8);
	
		while(1){
			//HAL_Delay(1000);
				do{
				UART_Forward();
			}while(0 == uart1_is_empty());
		}
	}else{
	OLED_ShowString(0, 0, (uint8_t *)"Registry success", 8);
	}
	return atRet;
}

NB_STA nbiot_check_reg(int iTimeout)
{
	/*
	AT+CGATT?

	+CGATT:1

	OK

	*/
	NB_STA atRet = NB_TIMEOUT;
	int ch = 0;// atRet = 2;//0 ok, 1 error, 2 pending
	char regFlag = 0, okFlag = 0;
	char *acCGATT = "+CGATT:1";
	char acOK[4] = {'O','K',0x0D,0x0A};
	nbiot_send_at_cmd(AT_R_CGATT, 500);
	do{
		ch = uart3_get_ch();
		if(ch){
			console_put_ch((uint8_t)ch);
			if(8 != regFlag){
				if(acCGATT[regFlag] == ch){
					regFlag++;
				}else{
					regFlag = 0;
				}
			}
			if(4 != okFlag){
				if(acOK[okFlag] == ch){
					okFlag++;
				}else{
					okFlag = 0;
				}
			}
			if(8 == regFlag && 4 == okFlag){
				atRet = NB_OK; break;
			}
			HAL_Delay(10);
		}else{
			if(0 != iTimeout) {
				HAL_Delay(1000);
				iTimeout--;
			}
		}
	}while(iTimeout);
	
	if(NB_OK == atRet){
		uart3_refresh_buf();
		printf("\nRegister success!\n");
	}
	return atRet;
}

NB_STA nbiot_check_LWM2M(int iTimeout)
{
	/*
	Responses will be of the format:
	
	+CEREG:1,3B00,08A2E16A,9
	+QLWEVTIND:3,xxxxxx
	*/
	NB_STA atRet = NB_TIMEOUT;
	int ch = 0;// atRet = 2;//0 ok, 1 error, 2 pending
	static char eventFlag = 0, regFlag = 0;
	char *acQLWEVTIND = "+QLWEVTIND:";
	char *acCEREGOK = "+CEREG:1";
	do{
		ch = uart3_get_ch();
		if(ch){
			console_put_ch((uint8_t)ch);
			if(11 != eventFlag){
				if(acQLWEVTIND[eventFlag] == ch){
					eventFlag++;
				}else{
					eventFlag = 0;
				}
			}
			
			if(8 != regFlag){
				if(acCEREGOK[regFlag] == ch){
					regFlag++;
				}else{
					regFlag = 0;
				}
			}
			
			if((11 == eventFlag || 8 == regFlag) && 0x0A == ch){
				atRet = NB_OK; break;
			}
			HAL_Delay(10);
		}else{
			if(0 != iTimeout) {
				HAL_Delay(1000);
				iTimeout--;
			}
		}
	}while(iTimeout);
	
	if(NB_OK == atRet){
		uart3_refresh_buf();
		printf("\nRegister success!\n");
		eventFlag = 0, regFlag = 0;
	}
	return atRet;
}

NB_STA nbiot_get_module_info(Message *pstMsg)
{
	NB_STA atRet = NB_TIMEOUT;
	int i = 0, j = 0, iLen = 0;
	char c = 0, flag = 0, tryCnt = 0;
	/*
		
	Quectel
	BC28
	Revision:BC28JAR01A07

	OK

	*/
	HAL_Delay(2000);
	uart3_refresh_buf();
	memset(pstMsg->aucModule, 0, sizeof(pstMsg->aucModule));
	memset(pstMsg->aucModuleVer, 0, sizeof(pstMsg->aucModuleVer));
	
	nbiot_send_at_cmd(AT_ATI, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(NB_OK == atRet){
		do{
			c = s_acAtBuf[i++];
			if(0x0D == c || 0x0A == c) {
				if(0x0A == c) flag++;
				continue;
			}
			if(':' == c){
				flag = 9; j = 0;
				continue;
			}
			if(1 == flag || 2 == flag){
				pstMsg->aucModule[j++] = c;
			}
			if(9 == flag){
				pstMsg->aucModuleVer[j++] = c;
			}
		}while(c);
	}
	printf("mVer:%s-%s\n", pstMsg->aucModule, pstMsg->aucModuleVer);
	
	memset(pstMsg->aucIMEI, 0, sizeof(pstMsg->aucIMEI));
	_again:	
	uart3_refresh_buf();
	flag = 0, i = 0, j = 0;
	nbiot_send_at_cmd(AT_W_CGSN, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(NB_OK == atRet){
		do{
			c = s_acAtBuf[i++];
			if(0x0D == c && 1 == flag) {break;}
			if(1 == flag){
				pstMsg->aucIMEI[j++] = c; continue;
			}
			if(':' == c && 0 == flag) {flag = 1;}	// get start
		}while(c);
	}
	printf("IMEI:%s\n", pstMsg->aucIMEI);
	if(15 != j){
		tryCnt++;
		if(5 == tryCnt) {return atRet;}
		goto _again;
	}
	return atRet;
}

NB_STA nbiot_get_signl_val(char *pcSigVal)
{
	//+CSQ:19,xx
	NB_STA atRet = NB_TIMEOUT;
	int iTimeout = 3, ch = 0;
	char csqFlag = 0, csqOk = 0, atOK = 0, atErr = 0;
	char *acCSQ = "+CSQ:";
	char acOK[] = {'O','K',0x0D,0x0A}, acErr[] = {'E','R','R','O','R',0x0D,0x0A};
	pcSigVal[0] = 0;pcSigVal[1] = 0;
	nbiot_send_at_cmd(AT_CSQ, 500);
	
	do{
		ch = uart3_get_ch();
		if(ch){
			console_put_ch((uint8_t)ch);
			if(acOK[atOK] == ch){
				atOK++;
			}else{
				atOK = 0;
			}
			if(4 == atOK && 1 == csqOk){
				atRet = NB_OK; break;
			}
			if(acErr[atErr] == ch){
				atErr++;
			}else{
				atErr = 0;
			}
			if(7 == atErr){
				atRet = NB_ERROR; break;
			}
			if(1 == csqOk){
				if(',' == ch) {
					csqFlag = 0x0F;
				}
				if(3 > csqFlag){
					pcSigVal[csqFlag++] = ch;
				}
				continue;
			}
			if(acCSQ[csqFlag] == ch){
				csqFlag++;
			}else{
				csqFlag = 0;
			}
			if(5 == csqFlag){csqOk = 1; csqFlag = 0;}
		}else{
			if(0 != iTimeout) {
				iTimeout--;
				if(0 != iTimeout){
					HAL_Delay(500);
				}
			}
		}
	}while(iTimeout);
	return atRet;
}

NB_STA nbiot_get_reg_sta(char *pcRegSta, char *pcLBS)
{
	/*
	+CEREG:x,1
	+CEREG:2,1,3B00,08A2E16A,9

	*/
	NB_STA atRet = NB_TIMEOUT;
	int iTimeout = 3 , ch = 0;
	char regFlag = 0, regOk = 0, len = 0, atOK = 0, atErr = 0;
	char *acREG = "+CEREG:";
	char acOK[] = {'O','K',0x0D,0x0A}, acErr[] = {'E','R','R','O','R',0x0D,0x0A};
	*pcRegSta = 0;
	
	nbiot_send_at_cmd(AT_R_CEREG, 500);
	do{
		ch = uart3_get_ch();
		if(ch){
			console_put_ch((uint8_t)ch);
			if(acOK[atOK] == ch){
				atOK++;
			}else{
				atOK = 0;
			}
			if(4 == atOK && 1 == regOk){
				printf("reg:%c,%s\r\n", *pcRegSta, pcLBS);
				atRet = NB_OK; break;
			}
			if(acErr[atErr] == ch){
				atErr++;
			}else{
				atErr = 0;
			}
			if(7 == atErr){
				atRet = NB_ERROR; break;
			}
			
			if(1 == regOk){
				if(',' == ch) {
					regFlag++;
					if(3 == regFlag){
						pcLBS[len++] = '|';
					}
					continue;
				}
				if(1 == regFlag){
					*pcRegSta = ch;
				}
				if(2 == regFlag || 3 == regFlag){
					if(len != 13){
						pcLBS[len++] = ch;
					}
				}
				continue;
			}
			if(acREG[regFlag] == ch){
				regFlag++;
			}else{
				regFlag = 0;
			}
			if(7 == regFlag){regOk = 1; regFlag = 0;}
		}else{
			if(0 != iTimeout) {
				iTimeout--;
				if(0 != iTimeout){
					HAL_Delay(500);
				}
			}
		}
	}while(iTimeout);
	return atRet;
}

NB_STA nbiot_get_nuestats(int *piRSRP, int *piSNR, int *piCellID, unsigned char *pucECL)
{
	/*
AT+NUESTATS

[2019-05-15 16:32:52.893]# RECV ASCII>

Signal power:-784
Total power:-687
TX power:-32768
TX time:0
RX time:311653
Cell ID:150360403
ECL:1
SNR:17
EARFCN:2506
PCI:495
RSRQ:-131
OPERATOR MODE:4

OK
*/
	NB_STA atRet = NB_TIMEOUT;
	int iTimeout = 3 , ch = 0, i = 0;
	
	char *pcRSRP="Signal power:", *pcSNR = "SNR:";
	char *pcCellID = "Cell ID:", *pcECL="ECL:";
	char acVal[15] = {0};
	char acOK[] = {'O','K',0x0D,0x0A}, acErr[] = {'E','R','R','O','R',0x0D,0x0A};
	
	char rsrpFlag = 0, snrFlag = 0, cidFlag = 0, eclFlag = 0, atOK = 0, atErr = 0;
	
	*piRSRP = 0; *piSNR = 0; *piCellID = 0; *pucECL = 0;
	
	nbiot_send_at_cmd(AT_R_NUESTATS, 10000);
	do{
		ch = uart3_get_ch();
		if(ch){
			console_put_ch((uint8_t)ch);
			if(acOK[atOK] == ch){
				atOK++;
			}else{
				atOK = 0;
			}
			if(4 == atOK){
				atRet = NB_OK; break;
			}
			if(acErr[atErr] == ch){
				atErr++;
			}else{
				atErr = 0;
			}
			if(7 == atErr){
				atRet = NB_ERROR; break;
			}
			if(13 == rsrpFlag){
				if(0x0D == ch){acVal[i] = 0; *piRSRP = atoi(acVal);  i = 0; rsrpFlag = 0; continue;}
				acVal[i++] = ch;
			}
			
			if(8 == cidFlag){
				if(0x0D == ch){acVal[i] = 0; *piCellID = atoi(acVal);  i = 0; cidFlag = 0; continue;}
				acVal[i++] = ch;
			}
			
			if(4 == eclFlag){
				if(0x0D == ch){acVal[i] = 0; *pucECL = (unsigned char)atoi(acVal);  i = 0; eclFlag = 0; continue;}
				acVal[i++] = ch;
			}
			
			if(4 == snrFlag){
				if(0x0D == ch){acVal[i] = 0; *piSNR = atoi(acVal);  i = 0; snrFlag = 0; continue;}
				acVal[i++] = ch;
			}
			//printf("%c-%d-%d-%d-%d\r\n", ch,rsrpFlag, cidFlag, eclFlag, snrFlag);	
			if(13 != rsrpFlag){
				if(pcRSRP[rsrpFlag] == ch){
					rsrpFlag++;
				}else{
					rsrpFlag = 0;
				}
			}
			if(8 != cidFlag){
				if(pcCellID[cidFlag] == ch){
					cidFlag++;
				}else{
					cidFlag = 0;
				}
			}
			if(4 != eclFlag){
				if(pcECL[eclFlag] == ch){
					eclFlag++;
				}else{
					eclFlag = 0;
				}
			}
			if(4 != snrFlag){
				if(pcSNR[snrFlag] == ch){
					snrFlag++;
				}else{
					snrFlag = 0;
				}
			}
		}else{
			if(0 != iTimeout) {
				iTimeout--;
				if(0 != iTimeout){
					HAL_Delay(1000);
				}
			}
		}
	}while(iTimeout);
	return atRet;
}

NB_STA nbiot_module_switch(char cSwitch)
{
	NB_STA atRet;
	int iLen = 0;
	if(1 == cSwitch){
		nbiot_send_at_cmd(AT_W_CFUN_1, 500);
	}else{
		nbiot_send_at_cmd(AT_W_CFUN_0, 500);
	}
	
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(20, s_acAtBuf, &iLen);
	
	return atRet;
}

void nbiot_module_restart(void)
{
	int iLen = 0;
	nbiot_send_at_cmd(AT_NRB, 500);
	OLED_ShowString(0, 0, (uint8_t *)"re-start module", 8);
	nbiot_send_at_cmd(AT_NRB, 1000);
	iLen = sizeof(s_acAtBuf);
	nbiot_recv_at_resp(20, s_acAtBuf, &iLen);
}

int nbiot_create_upd(int iPort)
{
	NB_STA atRet = NB_TIMEOUT;
	int fd = -1, i = 0, iLen = 0;
	char c = 0, flag = 0;
	//OLED_Show_GET_MODULE_INFO();

	memset(s_acAtBuf, 0, sizeof(s_acAtBuf));
	sprintf(s_acAtBuf, "AT+NSOCR=DGRAM,17,%d,1\r\n", iPort);
	//AT+NSOCR=DGRAM,17,3005,1
	nbiot_send_at_cmd(s_acAtBuf, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(NB_OK == atRet){
		do{
			c = s_acAtBuf[i++];
			if(0x0D == c && 1 == flag) {break;}
			if(1 == flag){
				fd = c-0x30; break;
			}
			if(0x0A == c && 0 == flag) {flag = 1;}	
		}while(c);
	}
	return fd;
}

NB_STA nbiot_udp_send(char *pcIP, int iPort, int socketId, unsigned char *pucData, int iLen, int iTimeout)
{
	NB_STA atRet = NB_TIMEOUT;
	int i = 0, iDlen = 0;
	memset(s_acAtBuf, 0, sizeof(s_acAtBuf));
	memset(s_acData, 0, sizeof(s_acData));
	for(i=0; i<iLen; i++){
		sprintf(&s_acData[iDlen], "%02X", pucData[i]);
		iDlen += 2;
		if(iDlen >= sizeof(s_acData)) break;
	}
	//printf("[%d]%s\n", iDlen, s_acData);
	iDlen >>=1;
	snprintf(s_acAtBuf, sizeof(s_acAtBuf), "AT+NSOST=%d,%s,%d,%d,%s\r\n", 
			socketId, pcIP, iPort, iDlen, s_acData);
	//72D764E1D91C -- 114.215.100.225:7385
	nbiot_send_at_cmd(s_acAtBuf, 2000);
	
	#if 0
	do{
		iLen = sizeof(s_acAtBuf);
		atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
		if(NB_OK == atRet || NB_ERROR == atRet) break;
		if(0 != iTimeout) {
			iTimeout--;
			if(0 != iTimeout){
				HAL_Delay(1000);
			}
		}
		//printf("s wait:%d\n",iTimeout);
	}while(iTimeout);
	#endif
	return atRet;
}

int nbiot_create_tcp(int iPort)
{
	int atRet = NB_TIMEOUT;
	int fd = -1, i = 0, iLen = 0;
	char c = 0, flag = 0;
	memset(s_acAtBuf, 0, sizeof(s_acAtBuf));
	sprintf(s_acAtBuf, "AT+NSOCR=STREAM,6,%d,1\r\n", iPort);
	nbiot_send_at_cmd(s_acAtBuf, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	if(0 == atRet){
		do{
			c = s_acAtBuf[i++];
			if(0x0D == c && 1 == flag) {break;}
			if(1 == flag){
				fd = c-0x30; break;
			}
			if(0x0A == c && 0 == flag) {flag = 1;}	
		}while(c);
	}
	return fd;
}

NB_STA nbiot_dns(const char *pcHost, char *pcIP, int iTimeout)
{
/*
AT+QDNS=0,"blog.hanxe.com"

OK

+QDNS:114.215.100.225	
	
+QDNS:FAIL
*/
	NB_STA atRet = NB_TIMEOUT;
	int ch = -1;
	char *acQDNS = "+QDNS:";
	char qdnsFlag = 0, sz = 0;
	char acShow[16] = {0};
	static char cTry = 0;
	OLED_ShowString(0, 0, (uint8_t *)"Get host ip ... ", 8);
	sprintf(acShow, "%d time", ++cTry);
	OLED_ShowString(0, 2, (uint8_t *)acShow, 8);
	memset(s_acAtBuf, 0, sizeof(s_acAtBuf));
	sprintf(s_acAtBuf, "AT+QDNS=0,\"%s\"\r\n", pcHost);
	nbiot_send_at_cmd(s_acAtBuf, 500);
	do{
		ch = uart3_get_ch();
		if(ch){
			console_put_ch((uint8_t)ch);
			
			if(6 != qdnsFlag){
				if(acQDNS[qdnsFlag] == ch){
					qdnsFlag++;
				}else{
					qdnsFlag = 0;
				}
			}else{
				if('F' == ch) {atRet = NB_ERROR;}
				
				if((0x30 <= ch && 0x39 >= ch) || '.' == ch){
					pcIP[sz++] = ch;
				}
				if(0x0A == ch) {
					if(7 < sz){atRet = NB_OK;}
					break;
				}
			}
		}else{
			if(0 != iTimeout) {
				HAL_Delay(1000);
				iTimeout--;
			}
		}
	}while(iTimeout);
	if(NB_OK == atRet){
		OLED_ShowString(0, 2, (uint8_t *)pcIP, 8);
	}
	return atRet;
}

NB_STA nbiot_tcp_connect(int fd, char *pcIP, int iPort)
{
	NB_STA atRet = NB_TIMEOUT;
	int iLen = 0;

	memset(s_acAtBuf, 0, sizeof(s_acAtBuf));
	sprintf(s_acAtBuf, "AT+NSOCO=%d,%s,%d\r\n", fd, pcIP, iPort);
	nbiot_send_at_cmd(s_acAtBuf, 500);
	iLen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(20, s_acAtBuf, &iLen);
	
	return atRet;
}

NB_STA nbiot_tcp_send(int socketId, unsigned char *pucData, int iLen, int iTimeout)
{
	NB_STA atRet = NB_TIMEOUT;
	int i = 0, iDlen = 0;
	memset(s_acAtBuf, 0, sizeof(s_acAtBuf));
	memset(s_acData, 0, sizeof(s_acData));
	for(i=0; i<iLen; i++){
		sprintf(&s_acData[iDlen], "%02X", pucData[i]);
		iDlen += 2;
		if(iDlen >= sizeof(s_acData)) break;
	}
	//printf("[%d]%s\n", iDlen, s_acData);
	iDlen >>=1;
	snprintf(s_acAtBuf, sizeof(s_acAtBuf), "AT+NSOSD=%d,%d,%s\r\n", 
			socketId, iDlen, s_acData);
	//72D764E1D91C -- 114.215.100.225:7385
	nbiot_send_at_cmd(s_acAtBuf, 2000);
	#if 0
	do{
		iLen = sizeof(s_acAtBuf);
		atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
		if(NB_OK == atRet || NB_ERROR == atRet) break;
		if(0 != iTimeout) {
			iTimeout--;
			if(0 != iTimeout){
				HAL_Delay(1000);
			}
		}
		//printf("s wait:%d\n",iTimeout);
	}while(iTimeout);
	#endif
	return atRet;
}

NB_STA nbiot_wait_data(Message *pstMsg, int iTimeout)
{
	//0 pending, 1 data read, 2 disconnected, 3 reg sta changed
	int ch = -1;
	NB_STA atRet = NB_TIMEOUT;
	char i = 0, fd = 0, acLenBuf[4] = {0};
	char *acNSONMI = "+NSONMI:",*acNSOCLI = "+NSOCLI:";
	char *acCSQ = "+CSQ:",*acCEREG = "+CEREG:";
	static char dataFlag = 0;
	char closeFlag = 0, csqFlag = 0, regFlag = 0;
	char dataOk = 0, closeOk = 0, csqOk = 0, regOk = 0;
	do{
		ch = uart3_get_ch();
		if(ch){
			console_put_ch((uint8_t)ch);
			
			if(1 == dataOk){//<CR><LF>+NSONMI:1,7<CR><LF>
				
				if(0 == fd && 0 == dataFlag){
					fd = ch-0x30;
					pstMsg->iFd = fd;
				}
				if(0x0A == ch && 1 == dataFlag){
					dataOk = 0; dataFlag = 0; i = 0; atRet = NB_DATA_IN;
					pstMsg->usRevLen = atoi(acLenBuf); break;
				}
				if(1 == dataFlag && 0x30 <= ch && 0x39 >= ch){
					if(3 != i){acLenBuf[i++] = ch;}
				}
				if(',' == ch){
					dataFlag = 1;
				}
			}
			
			/*==============================================*/
			if(0 == dataOk){
				if(acNSONMI[dataFlag] == ch){
					dataFlag++;
				}else{
					dataFlag = 0;
				}
				if(8 == dataFlag){dataOk = 1; dataFlag = 0; HAL_Delay(30);}
			}
			
			if(0 == closeOk){
				if(acNSOCLI[closeFlag] == ch){
					closeFlag++;
				}else{
					closeFlag = 0;
				}
				if(8 == closeFlag){closeOk = 1; closeFlag = 0; atRet = NB_NET_CLOSED;}
			}
			
			if(0 == csqOk){
				if(acCSQ[csqFlag] == ch){
					csqFlag++;
				}else{
					csqFlag = 0;
				}
				if(5 == csqFlag){csqOk = 1; csqFlag = 0;}
			}
			
			if(0 == regOk){
				if(acCEREG[regFlag] == ch){
					regFlag++;
				}else{
					regFlag = 0;
				}
				if(7 == regFlag){regOk = 1; regFlag = 0; atRet = NB_REG_CHANGED;}
			}
		}else{
			if(NB_TIMEOUT != atRet) break;
			if(0 != iTimeout) {
				HAL_Delay(500);
				iTimeout--;
			}
		}
	}while(iTimeout);
	if(NB_NET_CLOSED == atRet){
		printf("\ntcp be closing by remote server!\n");
	}else if(NB_REG_CHANGED == atRet){
		printf("\nregister has changed!\n");
	}
	
	return atRet;
}


NB_STA nbiot_data_recv(int iFd, int *piRlen, unsigned char *pcOut, int iSz, int iTimeout)
{
	NB_STA atRet = NB_TIMEOUT;
	int i = 0, j = 0, iDlen = *piRlen;
	char ch = 0, flag = 0;
	
	//memset(s_acRecv, 0, sizeof(s_acRecv));
	memset(s_acAtBuf, 0, sizeof(s_acAtBuf));
	*piRlen = 0;
	sprintf(s_acAtBuf, "AT+NSORF=%d,%d\r\n", iFd, iDlen);
	nbiot_send_at_cmd(s_acAtBuf, 1000);

	iDlen = sizeof(s_acAtBuf);
	atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iDlen);
	if(NB_OK == atRet){ // 1,120.24.184.124,8010,9,2F5BEEEBD91C010101,0
		do{
			ch = s_acAtBuf[i++];
			if(',' == ch && 4 == flag) {pcOut[j] = 0;break;}
			if(4 == flag){
				pcOut[j++] = ch;
				if(j == iSz) {pcOut[j] = 0;break;}
				continue;
			}
			if(',' == ch && 4 != flag) {flag++;}	
		}while(ch);
	}
	*piRlen = j;

	return atRet;
}

NB_STA nbiot_close_socket(int iFd)
{
	NB_STA ret = NB_TIMEOUT;
	int iLen = 0;
	memset(s_acAtBuf, 0, sizeof(s_acAtBuf));
	sprintf(s_acAtBuf, "AT+NSOCL=%d\r\n", iFd);
	//AT+NSOCR=DGRAM,17,3005,1
	nbiot_send_at_cmd(s_acAtBuf, 500);
	iLen = sizeof(s_acAtBuf);
	ret = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
	return ret;
}

NB_STA nbiot_coap_send(char *pcMsg, int iLen, int iTimeout)
{
	NB_STA atRet = NB_OK;
	int iDlen = 0;
	memset(s_acAtBuf, 0, sizeof(s_acAtBuf));
	iDlen = iLen>>1;
	snprintf(s_acAtBuf, sizeof(s_acAtBuf), "AT+NMGS=%d,%s\r\n", iDlen, pcMsg);
	
	nbiot_send_at_cmd(s_acAtBuf, 2000);
	//printf("MSG:%s:\n",s_acCmd);
	#if 0
	do{
		iLen = sizeof(s_acAtBuf);
		atRet = nbiot_recv_at_resp(2, s_acAtBuf, &iLen);
		if(NB_OK == atRet || NB_ERROR == atRet) break;
		if(0 != iTimeout) {
			iTimeout--;
			if(0 != iTimeout){
				HAL_Delay(1000);
			}
		}
	}while(iTimeout);
	#endif
	return atRet;
}

NB_STA nbiot_coap_wait(Message *pstMsg, int iTimeout)
{
	//0 pending, 1 data read, 2 disconnected, 3 reg sta changed
	int ch = -1;
	NB_STA atRet = NB_TIMEOUT;
	char acLenBuf[4] = {0};
	char *acNNMI = "+NNMI:";
	char *acCSQ = "+CSQ:";
	char acOK[] = {'O','K',0x0D,0x0A};
	char dataOk = 0, dataFlag = 0;
	char atOk = 0, atFlag = 0;
	char csqOk = 0, csqFlag = 0;
	int i = 0, iDateLen = 0;
	do{
		ch = uart3_get_ch();
		if(ch){
			console_put_ch((uint8_t)ch);
			
			if(1 == dataOk){//<CR><LF>+NNMI:4,AAAA0000<CR><LF> // +NNMI:5,0131320001
				if(0x30 <= ch && 0x39 >= ch && 0 == dataFlag){
					if(3 != i){acLenBuf[i++] = ch;}
				}
				if(0x0A == ch && 1 == dataFlag){
					dataOk = 0; dataFlag = 0; i = 0; atRet = NB_DATA_IN;
					pstMsg->usRevLen = iDateLen; break;
				}
				if(1 == dataFlag){
					if(MSG_DATA_BUFF_SZ != i && iDateLen != i && 0x0D != ch && 0x0A != ch){pstMsg->aucMsgData[i++] = ch;}
				}
				if(',' == ch){
					dataFlag = 1;
					iDateLen = atoi(acLenBuf);
					iDateLen <<=1;
					i = 0;
				}
				continue;
			}
			if(1 == csqOk){
				if(',' == ch) {
					csqOk = 0; csqFlag = 0;continue;
				}
				if(3 > csqFlag){
					pstMsg->aucSignal[csqFlag++] = ch;
				}
				continue;
			}
			/*==============================================*/
			if(0 == dataOk){
				if(acNNMI[dataFlag] == ch){
					dataFlag++;
				}else{
					dataFlag = 0;
				}
				if(6 == dataFlag){dataOk = 1; dataFlag = 0; HAL_Delay(30);}
			}
			
			if(0 == atOk){
				if(acOK[atFlag] == ch){
					atFlag++;
				}else{
					atFlag = 0;
				}
				if(4 == atFlag){atOk = 1; atFlag = 0; atRet = NB_OK; break;}
			}
			if(0 == csqOk){
				if(acCSQ[csqFlag] == ch){
					csqFlag++;
				}else{
					csqFlag = 0;
				}
			}
			if(5 == csqFlag){csqOk = 1; csqFlag = 0; pstMsg->aucSignal[0] = 0; pstMsg->aucSignal[1] = 0;}
		}else{
			if(NB_TIMEOUT != atRet) break;
			if(0 != iTimeout) {
				HAL_Delay(500);
				iTimeout--;
			}
		}
	}while(iTimeout);

	return atRet;
}

